/**
 * MKL - Tous droits réservés &copy; 2012 - 2014
 */
package com.mkl.leek.dpsSimulator.vo;

import org.apache.commons.lang.math.Range;

import java.math.BigDecimal;

/**
 * Range for BigDecimal.
 * <p>
 * Dernier commit:
 * <ul>
 * <li>le $Date:$</li>
 * <li>par $Author:$</li>
 * <li>revision $Revision:$</li>
 * </ul>
 * </p>
 *
 * @author MKL
 */

public class BigDecimalRange extends Range {
    /** Value min of range. Can't be <code>null</code>. */
    private BigDecimal minimum;
    /** Value max of range. Can't be <code>null</code>. */
    private BigDecimal maximum;

    /** Default constructor. */
    public BigDecimalRange() {
        this(BigDecimal.ZERO, BigDecimal.ZERO);
    }

    /**
     * Constructor with values.
     * The values does not need to be sorted (ie maximum value can be either first or second parameter).
     *
     * @param value1 one of the limits of the range.
     * @param value2 the other limit of the range.
     */
    public BigDecimalRange(BigDecimal value1, BigDecimal value2) {
        if (value1 == null) {
            value1 = BigDecimal.ZERO;
        }
        if (value2 == null) {
            value2 = BigDecimal.ZERO;
        }

        if (value1.compareTo(value2) > 0) {
            this.minimum = value2;
            this.maximum = value1;
        } else {
            this.minimum = value1;
            this.maximum = value2;
        }
    }

    /**
     * <p>Gets the minimum number in this range.</p>
     *
     * @return the minimum number in this range
     */
    @Override
    public BigDecimal getMinimumNumber() {
        return minimum;
    }

    /**
     * <p>Gets the maximum number in this range.</p>
     *
     * @return the maximum number in this range
     */
    @Override
    public BigDecimal getMaximumNumber() {
        return maximum;
    }

    /**
     * <p>Tests whether the specified <code>Number</code> occurs within
     * this range.</p>
     * <p/>
     * <p>The exact comparison implementation varies by subclass. It is
     * intended that an <code>int</code> specific subclass will compare using
     * <code>int</code> comparison.</p>
     * <p/>
     * <p><code>null</code> is handled and returns <code>false</code>.</p>
     *
     * @param number the number to test, may be <code>null</code>
     * @return <code>true</code> if the specified number occurs within this range
     * @throws IllegalArgumentException if the <code>Number</code> cannot be compared
     */
    @Override
    public boolean containsNumber(Number number) {
        return minimum.doubleValue() <= number.doubleValue()
                && number.doubleValue() <= maximum.doubleValue();
    }

    /**
     * Multiply this range by a value. Each limit of range will be multiply accordingly.
     *
     * @param multiply the factor of multiplication.
     * @return the BigDecimalRange that results of the multiplication.
     */
    public BigDecimalRange multiply(BigDecimal multiply) {
        return new BigDecimalRange(minimum.multiply(multiply), maximum.multiply(multiply));
    }

    /**
     * Add a range to this one. The limit are added by nature (min + min and max + max).
     *
     * @param range the range to add.
     * @return the BigDecimalRange that resulsts of the addition.
     */
    public BigDecimalRange add(BigDecimalRange range) {
        return new BigDecimalRange(minimum.add(range.getMinimumNumber()), maximum.add(range.getMaximumNumber()));
    }

    /**
     * Substracts this range by a value. Each limit of range will be substracted accordingly.
     *
     * @param substract the value to substract.
     * @return the BigDecimalRange that resulsts of the substraction.
     */
    public BigDecimalRange substract(BigDecimal substract) {
        BigDecimal min = minimum.subtract(substract);
        BigDecimal max = maximum.subtract(substract);
        if (min.compareTo(BigDecimal.ZERO) < 0) {
            min = BigDecimal.ZERO;
        }
        if (max.compareTo(BigDecimal.ZERO) < 0) {
            max = BigDecimal.ZERO;
        }
        return new BigDecimalRange(min, max);
    }

    /**
     * Substracts this range by another range.
     * The minimum will be substracted by the range maximum while
     * the maximum will be substracted by the range mininmum.
     *
     * @param range the range to substract.
     * @return the BigDecimalRange that results of the substraction.
     */
    public BigDecimalRange substract(BigDecimalRange range) {
        return new BigDecimalRange(minimum.subtract(range.maximum), maximum.subtract(range.minimum));
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("BigDecimalRange[")
                .append(minimum)
                .append(", ")
                .append(maximum)
                .append("]");
        return sb.toString();
    }
}
